package me.flyray.biz.thymeleaf.modules.pay.biz;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSONObject;
import com.github.wxiaoqi.security.biz.common.msg.BizResponseCode;
import com.github.wxiaoqi.security.common.util.AESUtils;
import com.github.wxiaoqi.security.common.util.HttpUtils;
import com.github.wxiaoqi.security.common.util.SnowFlake;

import me.flyray.biz.thymeleaf.feign.CrmFeign;
import me.flyray.biz.thymeleaf.feign.PayFeign;
import me.flyray.biz.thymeleaf.modules.goods.entity.QrGoodsInfo;
import me.flyray.biz.thymeleaf.modules.goods.entity.QrGoodsOrder;
import me.flyray.biz.thymeleaf.modules.goods.mapper.QrGoodsInfoMapper;
import me.flyray.biz.thymeleaf.modules.goods.mapper.QrGoodsOrderMapper;
import me.flyray.biz.thymeleaf.modules.pay.entity.CmsPayOrder;
import me.flyray.biz.thymeleaf.modules.pay.mapper.CmsPayOrderMapper;

/**
 * 支付
 * @author he
 *
 */
@Service
public class PayBiz {

	private static final Logger logger = (Logger) LoggerFactory.getLogger(PayBiz.class);

	@Autowired
	private PayFeign payFeign;
	@Autowired
	private CrmFeign crmFeign;
	@Autowired
	private CmsPayOrderMapper cmsPayOrderMapper;
	@Autowired
	private QrGoodsOrderMapper qrGoodsOrderMapper;
	@Autowired
	private QrGoodsInfoMapper qrGoodsInfoMapper;

	/**
	 * 创建订单并支付
	 * @param request
	 * @return
	 */
	public Map<String, Object> createAndPay(@RequestBody Map<String, Object> params){

		logger.info("创建订单并支付请求.......{}",params);
		Map<String, Object> respMap = new HashMap<String, Object>();
		//根据商户号获取商户名称
		String payOrderNo = String.valueOf(SnowFlake.getId());
		if(null == params.get("merchantId")){
			Map<String, Object> queryMerchantMap = new HashMap<String, Object>();
			queryMerchantMap.put("platformId",params.get("platformId"));
			queryMerchantMap.put("merchantId",params.get("merchantId"));
			Map<String, Object> merchantInfoMap= crmFeign.queryMerchantInfo(queryMerchantMap);
			Map<String, Object> merchantBase = (Map<String, Object>) merchantInfoMap.get("merchantBase");
			params.put("merchantName",merchantBase.get("merchantName"));
		}else{
			String scenesCode = (String) params.get("scenesCode");
			if("scenes001".equals(scenesCode)){//商品二维码
				QrGoodsInfo goodsInfo = new QrGoodsInfo();
				String extMap = (String) params.get("extMap");
				JSONObject jsonExtMap = (JSONObject) JSONObject.parse(extMap);
				goodsInfo.setGoodsId((String)jsonExtMap.get("goodsId"));
				goodsInfo.setPlatformId((String)params.get("platformId"));
				QrGoodsInfo queryGoodsInfo = qrGoodsInfoMapper.selectOne(goodsInfo);
				if(null != queryGoodsInfo){
					params.put("merchantId",queryGoodsInfo.getMerchantId());
				}
			}
		}
		//创建订单
		params.put("payOrderNo", payOrderNo);
		Map<String, Object> createPayOrderRespMap = payCoreCreatePayOrder(params);
		if(!BizResponseCode.OK.getCode().equals(createPayOrderRespMap.get("code"))){
			logger.info("创建订单并支付失败.......{}",createPayOrderRespMap.get("message"));
			respMap.put("success", false);
			respMap.put("code", createPayOrderRespMap.get("code"));
			respMap.put("message", createPayOrderRespMap.get("message"));
			return respMap;
		}

		BigDecimal fee = BigDecimal.ZERO;
		//计算手续费
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("platformId", (String)params.get("platformId"));
		param.put("merchantId", (String)params.get("merchantId"));
		param.put("payChannelNo", (String)params.get("payChannelNo"));
		param.put("payAmt", (String)params.get("payAmt"));
		param.put("outCustomerId", (String)params.get("outCustomerId"));
		Map<String, Object> queryMerChannelFee = crmFeign.queryMerChannelFee(param);
		logger.info("创建订单并支付手续费.......{}",queryMerChannelFee);
		if(BizResponseCode.OK.getCode().equals(queryMerChannelFee.get("code"))){
			String feeStr = (String)queryMerChannelFee.get("fee");
			fee = new BigDecimal(feeStr);
		}

		//发起支付
		params.put("payFee", String.valueOf(fee));
		Map<String, Object> doPayMap = payCoreDoPay(params);
		CmsPayOrder cmsPayOrder = new CmsPayOrder();
		if(!BizResponseCode.OK.getCode().equals(doPayMap.get("code"))){
			//创建支付订单
			cmsPayOrder.setTxStatus("01");//支付失败
			logger.info("创建订单并支付失败.......{}",doPayMap.get("message"));
			respMap.put("success", false);
			respMap.put("code", doPayMap.get("code"));
			respMap.put("message", doPayMap.get("message"));
		}else{
			//创建支付订单
			cmsPayOrder.setTxStatus("03");//支付中
			//创建场景订单
			this.createScenesOrder(params);
			respMap.put("payObject", doPayMap.get("payObject"));
			respMap.put("payOrderNo", payOrderNo);
			respMap.put("success", true);
			respMap.put("code", BizResponseCode.OK.getCode());
			respMap.put("message", BizResponseCode.OK.getMessage());
			//新增场景订单
			cmsPayOrder.setPlatformId((String)params.get("platformId"));
			cmsPayOrder.setMerchantId((String)params.get("merchantId"));
			cmsPayOrder.setCustomerId((String)params.get("customerId"));
			cmsPayOrder.setPayOrderNo((String)params.get("payOrderNo"));
			cmsPayOrder.setPayCode((String)params.get("payCode"));
			cmsPayOrder.setPersonalId((String)params.get("personalId"));
			String scenesCode = (String) params.get("scenesCode");
			cmsPayOrder.setScenesCode(scenesCode);
			cmsPayOrder.setTxAmt(new BigDecimal((String)params.get("payAmt")));
			cmsPayOrder.setCreateTime(new Date());
			cmsPayOrder.setTxFee(fee);
			cmsPayOrder.setExtMap((String)params.get("extMap"));
			cmsPayOrderMapper.insert(cmsPayOrder);
		}
		logger.info("创建订单并支付响应.......{}",respMap);
		return respMap;
	}

	/**
	 * 调用pay_core创建订单
	 * @param params
	 * @return
	 */
	private Map<String, Object> payCoreCreatePayOrder(Map<String, Object> params){
		Map<String, Object> createPayOrderMap = new HashMap<String, Object>();
		createPayOrderMap.put("platformId", (String)params.get("platformId"));
		createPayOrderMap.put("merchantId", (String)params.get("merchantId"));
		createPayOrderMap.put("merchantName", (String)params.get("merchantName"));
		createPayOrderMap.put("customerId", (String)params.get("customerId"));
		createPayOrderMap.put("payOrderNo", (String)params.get("payOrderNo"));
		createPayOrderMap.put("orderAmt", (String)params.get("orderAmt"));
		createPayOrderMap.put("payAmt", (String)params.get("payAmt"));
		createPayOrderMap.put("body", (String)params.get("body"));
		//1支付，2充值
		createPayOrderMap.put("payCode", (String)params.get("payCode"));
		logger.info("调用pay_core创建订单请求.......{}",createPayOrderMap);
		Map<String, Object> createRespMap = payFeign.createPayOrder(createPayOrderMap);
		logger.info("调用pay_core创建订单响应.......{}",createRespMap);
		return createRespMap;
	}

	/**
	 * 调用pay_core支付
	 * @param params
	 * @return
	 */
	private Map<String, Object> payCoreDoPay(Map<String, Object> params){
		Map<String, Object> doPayMap = new HashMap<String, Object>();
		doPayMap.put("platformId", (String)params.get("platformId"));
		doPayMap.put("payChannelNo", (String)params.get("payChannelNo"));//微信公众号/小程序支付
		doPayMap.put("payCompanyNo", (String)params.get("payCompanyNo"));//微信
		doPayMap.put("payOrderNo", (String)params.get("payOrderNo"));
		Map<String, Object> extValue = new HashMap<String, Object>();
		extValue.put("openId", (String)params.get("openId"));
		extValue.put("payType", (String)params.get("payType"));
		extValue.put("payStyle", (String)params.get("payStyle"));
		extValue.put("nickname", (String)params.get("nickname"));
		extValue.put("payAccount", (String)params.get("payAccount"));
		extValue.put("realname", (String)params.get("realname"));
		String extString = JSONUtils.toJSONString(extValue);
		doPayMap.put("extValue", extString);
		doPayMap.put("payFee", (String)params.get("payFee"));
		doPayMap.put("outCustomerId", (String)params.get("outCustomerId"));
		logger.info("调用pay_core支付请求.......{}",doPayMap);
		Map<String, Object> doPayRespMap = payFeign.doPay(doPayMap);
		logger.info("调用pay_core支付响应.......{}",doPayRespMap);
		return doPayRespMap;
	}

	/**
	 * 创建场景订单
	 * @param params
	 * @return
	 */
	private void createScenesOrder(Map<String, Object> params){
		String scenesCode = (String) params.get("scenesCode");
		if("scenes001".equals(scenesCode)){//商品二维码
			this.createQrGoodsOrder(params);
		}
	}

	/**
	 * 创建商品二维码订单
	 * @param params
	 * @return
	 */
	private void createQrGoodsOrder(Map<String, Object> params){
		QrGoodsOrder qrGoodsOrder = new QrGoodsOrder();
		qrGoodsOrder.setPlatformId((String)params.get("platformId"));
		qrGoodsOrder.setMerchantId((String)params.get("merchantId"));
		qrGoodsOrder.setPayOrderNo((String)params.get("payOrderNo"));
		qrGoodsOrder.setPayTime(new Date());
		qrGoodsOrder.setTxAmt(new BigDecimal((String)params.get("payAmt")));
		qrGoodsOrder.setStatus("02");//待支付
		String extMap = (String) params.get("extMap");
		JSONObject jsonExtMap = (JSONObject) JSONObject.parse(extMap);
		qrGoodsOrder.setGoodsId((String)jsonExtMap.get("goodsId"));
		qrGoodsOrder.setOpenId((String)params.get("openId"));
		qrGoodsOrder.setNickName((String)jsonExtMap.get("nickname"));
		qrGoodsOrderMapper.insert(qrGoodsOrder);
	}

	/**
	 * 支付完成通知商户
	 * @param request
	 * @return
	 */
	public Map<String, Object> callBack(@RequestBody Map<String, Object> params){
		logger.info("支付完成通知商户请求.......{}",params);
		Map<String, Object> respMap = new HashMap<String, Object>();
		String platformId = (String) params.get("platformId");
		String orderNo = (String) params.get("orderNo");
		String payAmt = (String)params.get("payAmt");
		CmsPayOrder cmsScenesOrder = new CmsPayOrder();
		cmsScenesOrder.setPlatformId(platformId);
		cmsScenesOrder.setPayOrderNo(orderNo);
		CmsPayOrder selectCmsPayOrder = cmsPayOrderMapper.selectOne(cmsScenesOrder);
		if(null == selectCmsPayOrder){
			logger.info("支付完成回调-订单不存在.......");
			respMap.put("success", false);
			respMap.put("code", BizResponseCode.ORDER_NO_EXIST.getCode());
			respMap.put("message", BizResponseCode.ORDER_NO_EXIST.getMessage());
			return respMap;
		}

		//修改订单金额
		if(!StringUtils.isEmpty(payAmt)){
			selectCmsPayOrder.setTxAmt(new BigDecimal(payAmt));
			cmsPayOrderMapper.updateByPrimaryKey(selectCmsPayOrder);
			//调用paycore修改订单金额
			payFeign.updatePayAmt(params);
		}
		
		//根据平台编号通知商户回调结果
		Map<String, Object> transportRequest = new HashMap<String, Object>();
		Map<String, Object> responseMap = null;
		Map<String, Object> queryUrlMap = new HashMap<String, Object>();
		queryUrlMap.put("platformId", (String) params.get("platformId"));
		queryUrlMap.put("callbackType", "00");//支付回调
		Map<String, Object> resMap = crmFeign.queryCallbackUrlByPlatformId(queryUrlMap);
		if(BizResponseCode.OK.getCode().equals((String)resMap.get("code"))){
			String callbackUrl = (String) resMap.get("callbackUrl");
			if(!StringUtils.isEmpty(callbackUrl)){
				Map<String, Object> request = new HashMap<String, Object>();
				request.put("order", orderNo);
				request.put("customerId", selectCmsPayOrder.getCustomerId());
				request.put("orderStatus", "00");
				request.put("orderType", "00");
				//参数加密
				net.sf.json.JSONObject json = net.sf.json.JSONObject.fromObject(request);
				String jsonSign = null;
				try {
					jsonSign = AESUtils.encrypt(json.toString(), (String) resMap.get("signKey"));
				} catch (Exception e1) {
					e1.printStackTrace();
				}
				transportRequest.put("param", jsonSign);

				int i = 0;
				do {
					i++;
					if (i > 2){ // 如果通知失败，尝试重新通知3次
						break;
					}
					try { // 通知商户
						logger.info("通知商户信息---request{}",transportRequest);
						responseMap = HttpUtils.httpPost(callbackUrl, transportRequest);
						responseMap.put("flag", "00");
					} catch (Exception e) {
						responseMap = new HashMap<String, Object>();
						responseMap.put("flag", "01");
						logger.error("通知商户信息失败", e);
					}
					logger.error("通知商户信息resMap.......{}", responseMap);
				} while (responseMap != null && "01".equals(responseMap.get("flag")));

				if("00".equals(responseMap.get("flag"))){
					//更新通知状态 
					payFeign.updatePayCallStatus(params);
				}
				respMap.put("success", true);
				respMap.put("code", BizResponseCode.OK.getCode());
				respMap.put("message", BizResponseCode.OK.getMessage());
			}else{
				respMap.put("success", false);
				respMap.put("code", BizResponseCode.URL_IS_NULL.getCode());
				respMap.put("message", BizResponseCode.URL_IS_NULL.getMessage());
			}
		}else{
			respMap.put("success", false);
			respMap.put("code", BizResponseCode.SERVICE_NOT_AVALIABLE.getCode());
			respMap.put("message", BizResponseCode.SERVICE_NOT_AVALIABLE.getMessage());
		}
		return respMap;

	}

}
